<template>
  <!-- #ifdef MP-WEIXIN || MP-TOUTIAO -->
  <canvas type="2d" class="echarts" :canvas-id="canvasId" :id="canvasId" @touchstart="touchStart" @touchmove="touchMove"
    @touchend="touchEnd" />
  <!-- #endif -->
  <!-- #ifndef MP-WEIXIN || MP-TOUTIAO -->
  <canvas class="echarts" :canvas-id="canvasId" :id="canvasId" @touchstart="touchStart" @touchmove="touchMove"
    @touchend="touchEnd" />
  <!-- #endif -->
</template>
<script>
  /**
   * echartsForUniApp echart兼容uni-app
   * @description echart兼容uni-app
   * @property {Object} option 图表数据
   * @property {String} canvasId 画布id
   * @example <echarts ref="echarts" :option="option" canvasId="echarts"></echarts>
   */
  import WxCanvas from './wx-canvas.js';
  import * as echarts from './echarts.min.js';

  var chartList = {};
  export default {
    props: {
      canvasId: {
        type: String,
        default: 'echarts'
      },
      option: {
        type: Object,
        default: () => {
          return {};
        }
      },
      pageProgress: {
        type: Number,
        default: () => {
          return 0;
        }
      },
      pageSize: {
        type: Number,
        default: () => {
          return 0;
        }
      }
    },
    watch: {
      option: {
        handler(newValue) {
          if (newValue.series) {
            this.initChart(newValue);
          }
        },
        deep: true
      }
    },
    data() {
      return {
        ctx: null,
        startPos: 0
      };
    },

    mounted() {
      echarts.registerPreprocessor((option) => {
        if (option && option.series) {
          if (option.series.length > 0) {
            option.series.forEach((series) => {
              series.progressive = 0;
            });
          } else if (typeof option.series === 'object') {
            option.series.progressive = 0;
          }
        }
      });
    },

    methods: {
      getCanvasAttr2d() {
        return new Promise((resolve, reject) => {
          const query = uni.createSelectorQuery().in(this);
          query
            .select('#' + this.canvasId)
            .fields({
              node: true,
              size: true
            })
            .exec((res) => {
              const canvasNode = res[0]?.node;
              if (canvasNode) {
                this.canvasNode = canvasNode;
                const canvasDpr = uni.getSystemInfoSync().pixelRatio;
                const canvasWidth = res[0].width;
                const canvasHeight = res[0].height;
                this.ctx = canvasNode.getContext('2d');

                const canvas = new WxCanvas(
                  this.ctx,
                  this.canvasId,
                  true,
                  canvasNode
                );
                echarts.setCanvasCreator(() => {
                  return canvas;
                });
                resolve({
                  canvas,
                  canvasWidth,
                  canvasHeight,
                  canvasDpr
                });
              }
            });
        });
      },
      getCanvasAttr() {
        return new Promise((resolve, reject) => {
          this.ctx = uni.createCanvasContext(this.canvasId, this);
          var canvas = new WxCanvas(this.ctx, this.canvasId, false);
          echarts.setCanvasCreator(() => {
            return canvas;
          });
          const canvasDpr = 1;
          var query = uni
            .createSelectorQuery()
            // #ifndef MP-ALIPAY
            .in(this);
          // #endif
          query
            .select('#' + this.canvasId)
            .boundingClientRect((res) => {
              const canvasWidth = res.width;
              const canvasHeight = res.height;
              resolve({
                canvas,
                canvasWidth,
                canvasHeight,
                canvasDpr
              });
            })
            .exec();
        });
      },
      // #ifdef H5
      //H5绘制图表
      initChart(option) {
        this.ctx = uni.createCanvasContext(this.canvasId, this);
        chartList[this.canvasId] = echarts.init(
          document.getElementById(this.canvasId)
        );
        chartList[this.canvasId].setOption(option ? option : this.option);
        chartList[this.canvasId].resize();
      },
      //H5生成图片
      canvasToTempFilePath(opt) {
        const base64 = chartList[this.canvasId].getDataURL();
        opt.success && opt.success({ tempFilePath: base64 });
      },
      // #endif
      // #ifndef H5
      //绘制图表
      async initChart(option) {
        const canvasAttr = await this.getCanvasAttr2d();
        const { canvas, canvasWidth, canvasHeight, canvasDpr } = canvasAttr;
        chartList[this.canvasId] = echarts.init(canvas, null, {
          width: canvasWidth,
          height: canvasHeight,
          devicePixelRatio: canvasDpr // new
        });
        canvas.setChart(chartList[this.canvasId]);
        chartList[this.canvasId].setOption(option ? option : this.option);
        if (chartList[this.canvasId]) {
          chartList[this.canvasId].getZr().on('click', (params) => {
            console.log('params', params)
            if (!params.topTarget) {
              return
            }
            const target = params.topTarget.parent
            Object.keys(target).forEach(key => {
              if (key.includes('__ec_inner')) {
                const domObj = target?.[key]
                const label = domObj?.labelEl?.style?.text
                this.$emit('clickItem', label)
              }
            })
          })
        }
      },
      //生成图片
      canvasToTempFilePath(opt) {
        // #ifdef MP-WEIXIN || MP-TOUTIAO
        var query = uni
          .createSelectorQuery()
          // #ifndef MP-ALIPAY
          .in(this);
        // #endif
        query
          .select('#' + this.canvasId)
          .fields({ node: true, size: true })
          .exec((res) => {
            const canvasNode = res[0].node;
            opt.canvas = canvasNode;
            uni.canvasToTempFilePath(opt, this);
          });
        // #endif
        // #ifndef MP-WEIXIN || MP-TOUTIAO
        if (!opt.canvasId) {
          opt.canvasId = this.canvasId;
        }
        this.ctx.draw(true, () => {
          uni.canvasToTempFilePath(opt, this);
        });
        // #endif
      },
      // #endif

      touchStart(e) {
        this.$emit('touchStart', e);
        if (chartList[this.canvasId] && e.touches.length > 0) {
          var touch = e.touches[0];
          this.startPos = touch.pageX;
          var handler = chartList[this.canvasId].getZr().handler;
          handler.dispatch('mousedown', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'start');
        }
      },
      touchMove(e) {
        const myChart = chartList?.[this.canvasId]
        if (myChart && e.touches.length > 0) {
          const handler = myChart.getZr().handler;
          const touch = e.touches[0];
          handler.dispatch('mousemove', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'change');
        }
      },

      touchEnd(e) {
        this.$emit('touchEnd', e);
        const myChart = chartList?.[this.canvasId]
        if (myChart) {
          const touch = e.changedTouches ? e.changedTouches[0] : {};
          const delta = this.startPos - touch.pageX;
          const zoom = myChart.getOption().dataZoom[0]
          let start = zoom.start
          let end = zoom.end
          if (delta < 0) {
            if (start > this.pageProgress * this.pageSize) {
              start = start - this.pageProgress * this.pageSize
              end = start + this.pageProgress * (this.pageSize - 1)
            } else {
              start = 0
              end = this.pageProgress * (this.pageSize - 1)
            }
          }
          if (delta > 0) {
            if (100 - end > this.pageProgress * this.pageSize) {
              end = end + this.pageProgress * this.pageSize
              start = end - this.pageProgress * (this.pageSize - 1)
            } else {
              start = 100 - this.pageProgress * (this.pageSize - 1)
              end = 100
            }
          }
          // console.log('pageProgress', this.pageProgress)
          // console.log('start', start)
          // console.log('end', end)
          myChart.setOption({
            dataZoom: [{ start, end }]
          });
          var handler = myChart.getZr().handler;
          handler.dispatch('mouseup', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.dispatch('click', {
            zrX: touch.x,
            zrY: touch.y
          });
          handler.processGesture(wrapTouch(e), 'end');
        }
      },
    }
  };

  function wrapTouch(event) {
    for (let i = 0; i < event.touches.length; ++i) {
      const touch = event.touches[i];
      touch.offsetX = touch.x;
      touch.offsetY = touch.y;
    }
    return event;
  }
</script>
<style lang="scss" scoped>
  .echarts {
    width: 100%;
    height: 100%;
  }
</style>